
/*******************************************************************************
* File Name          : main.c
* Version            : V1.0.0
* Date               : 11/13/2010
* Description        : Define main module.
											 This example project shows how to use the
											 FSSDC-9B506-EK board. It shows basic use of joy-stick,
											 ADC and PWM.
*******************************************************************************/
#include <intrinsics.h>
#include <stdio.h>
#include <stdlib.h>
#include <Fujitsu/iomb9bf506r.h>
#include <assert.h>

#include "project_pub.h"
#include "lcd_pub.h"

#include "board.h"
#include "lcd.h"
#include "key.h"
#include "adc.h"
#include "fujitsu_welcome.h"
#define TIMER0_TICK_PER_SEC   40

/*variable for clitical section entry control*/
Int32U CriticalSecCntr;
char disp[8] = { '\0' };
unsigned short AD_Data;
unsigned char LcdFlag;
unsigned short FlagCounter, VaulePwm;

/*************************************************************************
 * Function Name: NVIC_IntEnable
 * Parameters: IntNumber - Interrup number
 * Return: void
 *
 * Description: Enable interrup at NVIC
 *
 *
 *************************************************************************/
void NVIC_IntEnable (Int32U IntNumber)
{
    volatile unsigned long *pNVIC_SetEn = &SETENA0;

    assert ((NVIC_FCS <= IntNumber) && (NVIC_DMA_CH7 >= IntNumber));
    IntNumber -= NVIC_FCS;

    pNVIC_SetEn += IntNumber / 32;
    *pNVIC_SetEn = (1UL << (IntNumber % 32));

}

/*************************************************************************
 * Function Name: NVIC_IntDisable
 * Parameters: IntNumber - Interrup number
 * Return: void
 *
 * Description: Disables interrup at NVIC
 *
 *
 *************************************************************************/
void NVIC_IntDisable (Int32U IntNumber)
{
    volatile unsigned long *pNVIC_ClrEn = &CLRENA0;

    assert ((NVIC_FCS <= IntNumber) && (NVIC_DMA_CH7 >= IntNumber));
    IntNumber -= NVIC_FCS;

    pNVIC_ClrEn += IntNumber / 32;
    *pNVIC_ClrEn = (1UL << (IntNumber % 32));

}

/*************************************************************************
 * Function Name: NVIC_ClrPend
 * Parameters: IntNumber - Interrup number
 * Return: void
 *
 * Description:Clear pending interrupt at NVIC
 *
 *
 *************************************************************************/
void NVIC_ClrPend (Int32U IntNumber)
{
    volatile unsigned long *pNVIC_ClrPend = &CLRPEND0;

    assert ((NVIC_FCS <= IntNumber) && (NVIC_DMA_CH7 >= IntNumber));
    IntNumber -= NVIC_FCS;

    pNVIC_ClrPend += IntNumber / 32;
    *pNVIC_ClrPend = (1UL << (IntNumber % 32));

}

/*************************************************************************
 * Function Name: NVIC_ClrPend
 * Parameters: IntNumber - Interrup number, Interrupt Priority
 * Return: void
 *
 * Description:Sets Interrupt priority
 *
 *
 *************************************************************************/
void NVIC_IntPri (Int32U IntNumber, Int8U Priority)
{
    volatile Int8U *pNVIC_IntPri = (Int8U *) & IP0;

    assert ((NVIC_FCS <= IntNumber) && (NVIC_DMA_CH7 >= IntNumber));
    IntNumber -= NVIC_FCS;
    pNVIC_IntPri += IntNumber;
    *pNVIC_IntPri = Priority;
}

/*************************************************************************
 * Function Name: HWD_Disable
 * Parameters: None
 * Return: None
 *
 * Description:Disable HWD reset and interrupt
 *
 *
 *************************************************************************/
void HWD_Disable (void)
{
    /*Unlock sequence */
    WDG_LCK = 0x1ACCE551;
    WDG_LCK = 0xE5331AAE;
    WDG_CTL = 0;
}

/*************************************************************************
 * Function Name: InitClock
 * Parameters: void
 * Return: void
 *
 * Description: Initialize PLL to 80MHz,
 *              Base Clock  = 80MHz
 *              APB0 = APB1 = APB2 = 40MHz
 *
 *************************************************************************/
void InitClock (void)
{
    /*set Main clock stabilization
       wait time to 2ms */
    CSW_TMR_bit.MOWT = 9;
    /*Enable Main Oscilator */
    SCM_CTL_bit.MOSCE = 1;
    /*Wait stabilization end */
    while (!SCM_STR_bit.MORDY) ;
    /*Set PLL stabilization 
       wait time to 512uS */
    PSW_TMR_bit.POWT = 2;
    /*Set PLL to 80MHz */
    PLL_CTL1 = 0;               /*K = 1, M=1 */
    PLL_CTL2 = 19;              /*N = 20 */
    /*Enable PLL */
    SCM_CTL_bit.PLLE = 1;
    /*Set bus prescalers */
    BSC_PSR_bit.BSR = 0;        /*Base clock Prescaler 1:1 */
    APBC0_PSR_bit.APBC0 = 1;    /*APB0 clock Prescaler 1:2 */
    APBC1_PSR_bit.APBC1 = 1;    /*APB1 clock Prescaler 1:2 */
    APBC2_PSR_bit.APBC2 = 1;    /*APB2 clock Prescaler 1:2 */
    /*Wait PLL stabilizatoin end */
    while (!SCM_STR_bit.PLRDY) ;
    /*Select PLL for main clock */
    SCM_CTL_bit.RCS = 2;
    /*Wait PLL to be connected */
    while (2 != SCM_STR_bit.RCM) ;
}

/*************************************************************************
 * Function Name: GetBaseClock
 * Parameters: void
 * Return: Base Clock in HZ
 *
 * Description: 
 *              
 *************************************************************************/
Int32S GetBaseClock (void)
{
    Int32S clock = -1;
    Int32U n, k;

    switch (SCM_STR_bit.RCM)
    {
            /*Internal High Speed oscilator */
        case 0:
            clock = (CLKHC) / (BSC_PSR_bit.BSR + 1);
            break;
            /*Main oscilator */
        case 1:
            clock = (CLKMO) / (BSC_PSR_bit.BSR + 1);
            break;
         /*PLL*/ case 2:
            n = (PLL_CTL2_bit.PLLN + 1);
            k = (PLL_CTL1_bit.PLLK + 1);
            clock = ((CLKMO * n) / k) / (BSC_PSR_bit.BSR + 1);
            break;
            /*Internal Low Speed Oscilator */
        case 4:
            clock = (CLKLC) / (BSC_PSR_bit.BSR + 1);
            break;
            /*Sub Oscilator */
        case 5:
            clock = (CLKSO) / (BSC_PSR_bit.BSR + 1);
            break;
        default:
            break;
    }
    return clock;
}

/*************************************************************************
 * Function Name: InitLEDs
 * Parameters: void
 * Return: void
 *
 * Description: Init LED pins as outputs.
 *
 *************************************************************************/
void InitLEDs (void)
{
    /*Select CPIO function */
    LED_PFR &= ~LED_MASK;
    /*Set Pin to turn off leds */
    LED_PDOR |= LED_MASK;
    /*Make led pins outputs */
    LED_DDR |= LED_MASK;
//  LED_PDOR &= ~LED_MASK;
//  LED_DDR |= LED_MASK;
}

/*************************************************************************
 * Function Name: Init_LCD_IO
 * Parameters: void
 * Return: void
 *
 * Description: Init LCD Pins
 *		
 *************************************************************************/
void Init_LCD_IO ()
{
    /* Release the analog input function */
    ADE = 0x03;
    /*Select CPIO function */
    LCD_CS_PFR &= ~LCD_CS;
    /*Make pin output */
    LCD_CS_DDR |= LCD_CS;
    /*Select CPIO function */
    LCD_CD_PFR &= ~LCD_CD;
    /*Make pin output */
    LCD_CD_DDR |= LCD_CD;
    /*Select CPIO function */
    LCD_PS_PFR &= ~LCD_PS;
    /*Make pin output */
    LCD_PS_DDR |= LCD_PS;
    /*Select CPIO function */
    LCD_CLK_PFR &= ~LCD_CLK;
    /*Make pin output */
    LCD_CLK_DDR |= LCD_CLK;
    /*Select CPIO function */
    LCD_DATA_PFR &= ~LCD_DATA;
    /*Make pin output */
    LCD_DATA_DDR |= LCD_DATA;
}

/*************************************************************************
 * Function Name: Init_Joy_IO
 * Parameters: void
 * Return: void
 *
 * Description: Init Button pins as inputs.
 *
 *************************************************************************/
void Init_Joy_IO (void)
{
    /*Select CPIO function */
    JOY_PFR &= ~JOY_MASK;
    /*Set CPIO Pull-Up function */
    JOY_PCR |= JOY_MASK;
    /*Make button pins inputs */
    JOY_DDR &= ~JOY_MASK;
}

/*************************************************************************
 * Function Name: DelayResolution100us
 * Parameters: Int32U Dly
 * Return: void
 *
 * Description: Delay Dly * [100us]
 *		
 *************************************************************************/
void DelayResolution100us (Int32U Dly)
{
    volatile Int32U loop_100us;

    for (; Dly; Dly--)
    {
        for (loop_100us = 550; loop_100us; loop_100us--)
        {
        }
    }
}

VOID Progress_Test()
{
    UCHAR i = 0;
    while (i < 101)
    {
        PROGRESS_Center_Load(i);
        DelayResolution100us(10);
    }
}

int Tmr1Tick;

/*************************************************************************
 * Function Name: DT_QDU_IRQHandler
 * Parameters: none
 *
 * Return: none
 *
 * Description: Timer 1 interrupt handler
 *
 *************************************************************************/
void DT_QDU_IRQHandler (void)
{
    Tmr1Tick = 1;
    VaulePwm++;
    if (2038 == VaulePwm)
        VaulePwm = 10;
    if (1024 > VaulePwm)
        Update_PWM (VaulePwm);
    else
        Update_PWM (2048 - VaulePwm);
    Timer1IntClr = 1;
}

/*************************************************************************
 * Function Name: main
 * Parameters: none
 *
 * Return: none
 *
 * Description: main
 *
 *************************************************************************/
int main (void)
{
    unsigned char i = 0;
    unsigned long AD_Data_temp = 0;

    /* Init LCD Pins */
    InitClock ();
    /* Disable Hardware Watchdog */
    HWD_Disable ();
    /* Init LCD Pins */
    Init_LCD_IO ();
    /* Init LCD */
    LCD_Initialize ();
    /* Delay */
    DelayResolution100us (100);
    /* Display welcome */
    LCD_FillAll (Fujitsu_Welcome);
    /* Init LEDs */
    InitLEDs ();
    /* Init Joy-sticks */
    Init_Joy_IO ();
    Keyboard_Init ();
    /* Init ADC conversion */
    Init_ADC ();
    /* Init PWM output */
    Init_PWM ();
    VaulePwm = 10;

    /*Set Timer 1 Load Value */
    Timer1Load = GetBaseClock ()    /* Base Clock */
        / 2                     /* APB Devider */
        / 256                   /* Timer devider */
        / 1000;                 /* 1000 times per second */
    /*Set Timer 1 Mode */
    Timer1Control = (0 << 0) |  /*wrapping mode */
        (1 << 1) |              /*1 = 32-bit counter */
        (2 << 2) |              /*8 stages of prescale, clock is divided by 256 */
        (1 << 5) |              /*Interrupt Enable */
        (1 << 6) |              /*Timer is in periodic mode */
        (1 << 7);               /*Timer enabled */
    /*Enable Dual Timer Interrup */
    NVIC_IntEnable (NVIC_DT_QDU);

    /*Main Loop */
    while (1)
    {
        Keyboard_Exec ();
        /*Wait for timer tick */
        if (Tmr1Tick)
        {                       /*Clear timer tick flag */
            Tmr1Tick = 0;
            FlagCounter++;
            if (FlagCounter > 1000)
            {
                FlagCounter = 0;
                if ((abs (AD_Data_temp - AD_Data) < 100) && (0 != LcdFlag))
                {
                    LCD_ClearSCR ();
                    LCD_FillAll (Fujitsu_Welcome);
                    LcdFlag = 0;
                }
            }
        }
        if (1 != (IOREG_ADSR_U0 & 0x1))
        {
            AD_Data_temp = IOREG_SCFD_U0;
            AD_Data_temp = AD_Data_temp >> 20;
            AD_Data_temp = (AD_Data_temp * 3300) / 4096;
            sprintf (disp, "%d", (unsigned short)AD_Data_temp);

//          IOREG_ADCEN_U0 |= 0x01;
            IOREG_SCCR_U0 |= 0x01;  /* A/DC start */
        }
        if (abs (AD_Data_temp - AD_Data) > 20)
        {
            for (i = 0; i < (sizeof (disp) - 1); i++)
            {
                if ((disp[i] > 0x39) || (disp[i] < 0x30))
                {
                    disp[i] = ' ';
                    disp[i + 1] = 'm';
                    disp[i + 2] = '|';
                    for (i = i + 3; i < (sizeof (disp) - 1); i++)
                        disp[i] = ' ';
                    break;
                }
            }
            AD_Data = (unsigned short)AD_Data_temp;
            AD_Data_temp = 0;
            FlagCounter = 0;
            if (2 != LcdFlag)
            {
                LCD_ClearSCR ();
                LCD_PutString (36, 18, "ADC data");
                LcdFlag = 2;
            }
            LCD_PutString (38, 36, disp);
            //LCD_DislayHorLine(0, 48, 128);
            LCD_DisplayHorLine(1, 7, 128, 1);
            LCD_DisplayHorLine(1, 8, 40, 1);
            LCD_DisplayHorLine(1, 16, 128, 1);
            LCD_DisplayHorLine(1, 24, 40, 1);
            LCD_DisplayHorLine(1, 32, 10, 1);
            LCD_DisplayHorLine(1, 40, 10, 1);
            LCD_DisplayHorLine(1, 48, 128, 1);
            LCD_DisplayHorLine(1, 63, 40, 1);
            LCD_DisplayVerLine(4, 23, 16);
        }

    }
}
